'static ライフタイム
from 項目14:生存期間を理解しよう
'static は、プログラム 実行中の全期間にわたって有効な 生存期間 を表す
引数で 参照 値を受け取らないが参照値を返す場合、'static を指定する必要がある
pub fn the_answer() -> &Item: コンパイルエラー
pub fn the_answer() -> &'static Item
これにより、戻り値が決して スコープ から外れないことを保証できる
'static ライフタイムを持つ値を取得する方法
1. static な グローバル変数 への参照を取得すること
コンパイラは static な値をプログラム中の実行中は常に同じアドレスに存在し、ムーブしないことを保証するため、参照のライフタイムは常に 'static となる
code:rs
static ANSWER: Item = Item { contents: 42 };
pub the answer() -> &'static Item {
&ANSWER
}
2. const な値への参照を 'static ライフタイムに 昇格 する
warning.icon ただし、2 点ほど注意が必要
1. その型に デストラクタ(Drop) や 内部可変性(RefCell, Mutex, RwLock)を持つ場合は昇格されない
したがって、以下はコンパイルエラーとなる
code:rs
pub struct Wrapper(pub i32);
impl Drop for Wrapper {
fn drop(&mut self) {}
}
const ANSWER: Wrapper = Wrapper(42);
pub fn the_answer() -> &'static Wrapper {
&ANSWER
}
2. const はメモリアドレスは固定されない
const の値は変更されないがコピーを作成することが可能であるため、常に同じ メモリアドレス を指す保証はない
3. ヒープ に割り当てた値を 'static として扱う
通常、ヒープ上に確保された値(Box<T>)は要素が ドロップ されないことを保証できないため、この条件を満たさない
code:rs
// コンパイルエラー
{
let boxed = Box::new(Item { contents: 42 });
let r: &static Item = &boxed;
println!("'static item is {r:?}");
}
しかし、Box::leak 関数を使えば、所有 された Box<T> を 消費 して T の 可変参照 に変換することができる
この値の 所有者 はいない ため、ドロップされることもないことを保証できる
code:rs
{
let boxed = Box::new(Item { contents: 42 });
let r: &static Item = Box::leak(boxed);
println!("'static item is {r:?}");
}
warning.icon ヒープに割り当てた値が永遠に解放されないため、メモリリーク が発生する可能性がある
ただし、メモリリークが発生しても Rust の メモリ安全性 に影響を及ぼさない
#Rust #Effective_Rust_―_Rustコードを改善し、エコシステムを最大限に活用するための35項目